﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Taobao.Top.Api;
using System.Threading;
using System.IO;
using TaobaoDistrSales.Model;

namespace TaobaoDistrSales.Common
{
    public class TaobaoProcessor:IProcessor
    {
        private static readonly object lockObj =new object();
        public const int ThreadSleepTick =500;
        protected taobaodbEntities Entities = null;

        #region Ctor

        public TaobaoProcessor(Model.Shop shop)
            :this(shop.ShopId)
        { 
        }

        public TaobaoProcessor(short shopid)
        {
            try
            {
                Entities = ResourceManager.Current.LoadEntity();
                var shops = from s in Entities.Shop
                            where s.ShopId == shopid
                            select s;

                Shop = shops.FirstOrDefault();
            }
            catch { }

            if (Shop != null)
            {
                Client = new TopXmlRestClient(ResourceManager.Current.RequestUrl, AppKey, AppSecret);
                ShopID = shopid;
            }
            else
            {
                OutputWriter.WriteLine("对不起，没有该店铺的信息！", OutputFormatType.Error);
            }
        }

        public TaobaoProcessor(short shopid, IOutputWriter textWriter)
            :this(shopid)
        {
            OutputWriter = textWriter;
        }

        #endregion

        #region Fields
         
        protected Thread JobThread;
         

        #endregion

        #region Events

        public event ProcessCompletedEventHandler ProcessCompleted;
        public event Action<Model.Shop> ShopChanged;

        #endregion

        #region Properties

        public IOutputWriter OutputWriter
        {
            get;
            set;
        }

        protected string AppKey
        {
            get
            {
                return Shop.AppKey;
            }
        }

        protected string AppSecret
        {
            get
            {
                return Shop.AppSecret;
            }
        }

        public string ShopName
        {
            get
            {
                return Shop.Name;
            }
        }

        public TopXmlRestClient Client
        {
            get;
            private set;
        }

        public ProcessStatus Status
        {
            get;
            set;
        }

 
        protected Model.Shop Shop;

        private short shopID;
        public short ShopID
        {
            get
            {
                return shopID;
            }
            protected set
            {
                shopID = value;
                try
                {
                    Shop = Entities.Shop.FirstOrDefault();
                    if (ShopChanged != null && Shop!=null)
                        ShopChanged(Shop);
                }
                catch { }
            }
        }

        public Action<string> UpdateStatus;

        #endregion

        #region Virtual Methods

        protected virtual void OnProcessCompleted(EventArgs e)
        {
            if (ProcessCompleted != null)
            {
                ProcessCompleted(this, e);
            }
        }

        protected virtual void DoExcuteJob() { }

        #endregion

        #region Main Methods 

        public void ExcuteJob()
        {
            DoExcuteJob();
        }

        protected void InitializeEntities()
        {
            try
            {
                Entities = ResourceManager.Current.LoadEntity();
                Shop = Entities.Shop.FirstOrDefault();
            }
            catch { }
        }
        protected void DisposeEntities()
        {
            try
            {
                ResourceManager.Current.DisposeEntity(Entities);
            }
            catch { }
        }


        #endregion

        #region IProcessor Members

        public virtual void Start()
        {
            try
            {
                JobThread = null;
                JobThread = new Thread(new ThreadStart(ExcuteJob));
                JobThread.IsBackground = true;
                JobThread.Priority = ThreadPriority.Lowest;
                JobThread.Start();
                OutputWriter.WriteLine("API处理启动...", OutputFormatType.Title);
                Status = ProcessStatus.Started;
            }
            catch { }
        }

        public virtual void Suspend()
        {
            try
            {
                Thread.Sleep(ThreadSleepTick);
                JobThread.Suspend();
                Status = ProcessStatus.Suspended;
                Thread.Sleep(ThreadSleepTick);
                OutputWriter.WriteLine("API处理暂停...", OutputFormatType.Title);
            }
            catch { }
        }

        public virtual void Resume()
        {
            try
            {
                Thread.Sleep(ThreadSleepTick);
                JobThread.Resume();
                Thread.Sleep(ThreadSleepTick);
                Status = ProcessStatus.Resumed;
                OutputWriter.WriteLine("API处理继续...", OutputFormatType.Title);
            }
            catch { }
        }

        public virtual void Stop()
        {
            try
            {
                if (JobThread.IsAlive)
                {
                    JobThread.Abort();
                }
            }
            catch { }
            finally
            {
                OutputWriter.WriteLine("API处理停止！", OutputFormatType.Title);
                //JobThread = null; 
                Status = ProcessStatus.Stoped;
                Thread.Sleep(ThreadSleepTick);
            }
        }

        #endregion

        #region Clear Output

        public void Clear()
        {
            if (Status == ProcessStatus.Resumed
                || Status == ProcessStatus.Started)
            {
                try
                {
                    Thread.Sleep(ThreadSleepTick);
                    JobThread.Suspend();

                    //LogToFile();

                    OutputWriter.Clear();
                    Thread.Sleep(ThreadSleepTick);
                    JobThread.Resume();
                }
                catch { }
            }
            else
            {
                try
                {
                    Thread.Sleep(ThreadSleepTick);
                    OutputWriter.Clear();
                }
                catch { }
            }
        }

        #endregion

        #region Exception Handler

        protected void HandleException(string displayMessage, Exception e)
        {
            HandleException(displayMessage, e, true);
        }

        protected void HandleException(string displayMessage, Exception e,bool display)
        {
            try
            {
                DistrSalesException dException = new DistrSalesException(displayMessage, e);
                if (display)
                {
                    OutputWriter.WriteLine(displayMessage, OutputFormatType.Exception);
                }
                //Log the exception to DB
                Logger.Write("taobaofenxiao", LogType.Exception,
                    "DisplayMessage: " + displayMessage + ";ExceptionMessage:" + e.Message,
                    e.StackTrace.Substring(0, e.StackTrace.Length > 1900 ? 1900 : e.StackTrace.Length), ShopID);
            }
            catch { }
        }

        #endregion

        #region Update Status

        protected void ExcuteUpdateStatus(string statusInfo)
        {
            try
            {
                if (Status == ProcessStatus.Started || Status == ProcessStatus.Resumed)
                {
                    if (UpdateStatus != null)
                    {
                        UpdateStatus.Invoke(statusInfo);
                        //UpdateStatus(statusInfo);
                    }
                }
                //Logger.Write("taobaofenxiao", LogType.Normal, statusInfo, statusInfo, Shop);
            }
            catch { }
        }

        #endregion

        #region Assist Methods

        protected DateTime? ConvertDateTime(string datetime)
        {
            DateTime value = DateTime.MinValue;
            if (!String.IsNullOrEmpty(datetime))
            {
                DateTime.TryParse(datetime, out value);   
            }
            if (value != DateTime.MinValue)
                return value;
            return null;
        }


        protected void LogstatisticsEnd(string contentTitle, long total, long success)
        {
            try
            {
                StringBuilder logBuilder = new StringBuilder();
                logBuilder.AppendFormat("{0}处理结束。", contentTitle);
                OutputWriter.WriteLine(logBuilder.ToString(), OutputFormatType.Title);

                if (total > 0)
                {
                    logBuilder = new StringBuilder();
                    logBuilder.AppendFormat("总共：{0} 条{1}需要处理，成功处理了{2}条，失败了 {3}条。", total, contentTitle, success, total - success);
                    OutputWriter.WriteLine(logBuilder.ToString(), OutputFormatType.Title);
                }
                OutputWriter.WriteLine("");
            }
            catch { }
        }

        protected void LogstatisticsStart(string contentTitle, long total)
        {
            try
            {
                StringBuilder logBuilder = new StringBuilder();
                if (total > 0)
                {
                    logBuilder.AppendFormat("总共：{0} 条{1}需要处理...", total, contentTitle);
                }
                else
                {
                    logBuilder.AppendFormat("没有{0}需要处理。", contentTitle);
                }
                OutputWriter.WriteLine(logBuilder.ToString(), OutputFormatType.Title);
            }
            catch { }
        }
        #endregion

        #region Dispose

        public void Dispose()
        {
            if (JobThread != null && JobThread.IsAlive)
            {
                try
                {
                    JobThread.Abort();
                }
                catch { }
                finally
                {
                    JobThread = null;
                    GC.Collect();
                }
            }
        }

        #endregion

        #region  Log to File

        public void LogToFile()
        {
            try
            {
                string logFolder = Path.Combine(Environment.CurrentDirectory, "/log");
                if (!Directory.Exists(logFolder))
                {
                    Directory.CreateDirectory(logFolder);
                }
                string fileName = logFolder + "/" + DateTime.Now.ToString("yyyy_mm_dd_hh_MM_SS") + ShopID.ToString();
                Logger.WriteLogToFile(fileName, OutputWriter.GetOutputText());
            }
            catch { }
        }

        #endregion
    }

    public delegate void ProcessCompletedEventHandler(object sender,EventArgs e);

    public enum ProcessStatus
    {
        None,
        Started,
        Suspended,
        Resumed,
        Stoped
    }
}
